#-*- coding:utf-8 -*-
'''
Created on Sep 12, 2012

@author: johnny
'''
import Queue, time, datetime
import os, logging, uuid

import base_test, runner, test_db
from errors import error
from utils import logging_manager
from utils import logging_config
from utils import configer
from utils import reporter

class CommonLoggingConfig(logging_config.LoggingConfig):
    pass

class Job(object):
    def __init__(self, testname):
        self.test = None
        self.logging = logging_manager.get_logging_manager(
                manage_stdout_and_stderr=True, redirect_fds=True)
        self.results = None
        self.start_time = ""
        self.end_time = ""
        self.output = ""
        
        self.add_test(testname)
        #self.uid = None
        self._set_id()
    
    def add_test(self, name):
        test = base_test.Test()

        try:
            test.add_test_by_name(name)
        except error.CommonError, e:
            logging.error(str(e))
        self.test = test
        self.test_name = name
    
    def _set_id(self):
        self.uid = uuid.uuid1()
    
    def set_base_result_dir(self, base):
        self.base_dir = base
    
    def skip(self):
        self.results = "SKIPPED"
    
    def run(self, log_to_file = True):
        #self._set_id()
        if not self.test:
            return
        
        self.start_time = datetime.datetime.now().\
                          strftime("%Y%m%d %H:%M:%S.%f")
        self.output = os.path.join(self.base_dir, self.start_time)
        self.output = os.path.abspath(self.output)
        if not os.path.exists(self.output):
            os.makedirs(self.output)
        
        filepath = os.path.join(self.output, 'logs')
        self.output = filepath
        
        if log_to_file:
            self.logging.tee_redirect(filepath)
        
        self.test.run_test()
        self.results = self.test.get_results()
        
        self.end_time = datetime.datetime.now().strftime("%Y%m%d %H:%M:%S.%f")

def load_all_jobs():
    names = base_test.get_cases_base_name()
    return [Job(name) for name in names]


class Group(object):
    pass
         
        
class JobManager(object):
    job_queue = Queue.Queue()
    results_queue = Queue.Queue()
    
    def __init__(self):
        logging_manager.configure_logging(
                CommonLoggingConfig(), 
                use_console=True,
                verbose=False)
        self.configer = configer.Configer()
        self.configer.set_config_file()
        self.configer.parse_config_file()
        self.results = []
        self.db = test_db.TestDB()
        self.job_count = 0
        
        self.db.delete_all()
    
    def add_job(self, job):
        JobManager.job_queue.put(job)
        self.db.insert1('current_tests',
                        (job.uid, job.test_name, "PENDDING"))
        self.job_count += 1
        
        
    def add_jobs(self, jobs):
        if isinstance(jobs, list):
            for job in jobs:
                JobManager.job_queue.put(job)
                self.db.insert1('current_tests',
                        (job.uid, job.test_name, "PENDDING"))
                self.job_count += 1
        else:
            logging.error("Add jobs failed!")
        
        
    def clear_job_queue(self):
        while True:
            try:
                JobManager.job_queue.get(timeout=1)
            except Queue.Empty:
                break
            
    def _get_all_results1(self):
        while True:
            try:
                self.results.append(JobManager.results_queue.get(timeout=1))
            except Queue.Empty:
                break
            
    def _get_all_results(self):
        while True:
            try:
                jb = self.results_queue.get(timeout=1)
                self.results.append((jb.uid, jb.test_name, jb.start_time,
                                     jb.end_time, jb.results, jb.output))
            except Queue.Empty:
                break
    
    def parse_results(self):
        results = []
        for rs in self.results:
            rst_dict = {}
            uid, name, s_time, e_time, rst_obj, log_path = rs
            rst_dict['uid'] = uid
            rst_dict['name'] = name
            rst_dict['start_time'] = s_time
            rst_dict['end_time'] = e_time
            rst_dict['log_path'] = log_path
            if "SKIPPED" == rst_obj:
                rst_dict['result'] = 'SKIPPED'
                rst_dict['error_instance'] = ''
                rst_dict['traceback'] = ''
            elif not rst_obj.wasSuccessful():
                rst_dict['result'] = "FAILED"
                error_instance = rst_obj.errors[0][0]
                traceback = rst_obj.errors[0][1]
                rst_dict['error_instance'] = str(error_instance)
                rst_dict['traceback'] = traceback
            else:
                rst_dict['result'] = 'PASSED'
                rst_dict['error_instance'] = ''
                rst_dict['traceback'] = ''
            results.append(rst_dict)
        return results
    
    def write_db(self, data):
        for i in data:
            if isinstance(i, dict):
                self.db.insert('results', i)
        
    def report_output(self, start_time, time_consum, results):
        if self.output:
            reporter.write_report(start_time, time_consum,
                                  results, self.output)
    
    def start_jobs(self, report=True):
        logging.info(">> START")
        self.db.update_progress('STARTING', '0%')
        resultdir = self.configer.get_config_value('common', 'resultdir')
        
        start_time = time.time()
        start_time_str = time.strftime("%Y%m%d %H:%M:%S", time.localtime())
        
        results = 'results.' + start_time_str
        self.output = os.path.join(resultdir, results)
        self.output = os.path.abspath(self.output)
        
        self.runner = runner.Runner(JobManager.job_queue,
                                    JobManager.results_queue, self.job_count)
        self.runner.run(self.output)
        
        end_time = time.time()
        time_consum = round(end_time - start_time)
        self._get_all_results()
        #Move to runner.py
        #self.write_db(self.parse_results())
        
        if report:
            self.report_output(start_time_str, time_consum, self.parse_results())
        
        self.db.update_progress('FINISHED', '100%')
        logging.info("<< END")
        
        